import 'dart:convert';

import 'package:copilot_proxy/common.dart';
import 'package:copilot_proxy/context.dart';
import 'package:copilot_proxy/middleware/middleware.dart';
import 'package:copilot_proxy/utils/json_util.dart';

final Map<String, String> _accessTokenClientIdMap = {};

final Map<String, JsonMap> _clientIdUserInfoMap = {};

void addAccessToken(String accessToken, String clientId) {
  final fakeUser = generateFakeUser();
  _clientIdUserInfoMap[clientId] = fakeUser;
  _accessTokenClientIdMap[accessToken] = clientId;
}

bool isAccessTokenValid(String accessToken) => _accessTokenClientIdMap.containsKey(accessToken);

String? getClientId(String accessToken) => _accessTokenClientIdMap[accessToken];

JsonMap? getUserInfoByAccessToken(String accessToken) => _clientIdUserInfoMap[getClientId(accessToken)];

JsonMap? getUserInfoByClientId(String clientId) => _clientIdUserInfoMap[clientId];

JsonMap generateFakeUser() {
  final now = DateTime.now();
  final createdAt = now.subtract(Duration(days: random.nextInt(3650) + 365));
  final updatedAt = createdAt.add(Duration(days: random.nextInt(3650)));

  return {
    'login': 'fakeuser${random.nextInt(10000)}',
    'id': random.nextInt(10000),
    'node_id': 'MDQ6VXNlcj${base64Encode(random.nextInt(10000).toString().codeUnits)}',
    'avatar_url': 'https://avatars.githubusercontent.com/u/${random.nextInt(10000)}?v=4',
    'gravatar_id': '',
    'url': 'https://api.github.com/users/fakeuser',
    'html_url': 'https://github.com/fakeuser',
    'followers_url': 'https://api.github.com/users/fakeuser/followers',
    'following_url': 'https://api.github.com/users/fakeuser/following{/other_user}',
    'gists_url': 'https://api.github.com/users/fakeuser/gists{/gist_id}',
    'starred_url': 'https://api.github.com/users/fakeuser/starred{/owner}{/repo}',
    'subscriptions_url': 'https://api.github.com/users/fakeuser/subscriptions',
    'organizations_url': 'https://api.github.com/users/fakeuser/orgs',
    'repos_url': 'https://api.github.com/users/fakeuser/repos',
    'events_url': 'https://api.github.com/users/fakeuser/events{/privacy}',
    'received_events_url': 'https://api.github.com/users/fakeuser/received_events',
    'type': 'User',
    'site_admin': false,
    'name': 'Fake User ${random.nextInt(1000)}',
    'company': 'FakeCompany',
    'blog': 'https://fakeblog.com',
    'location': 'FakeCity',
    'email': 'fakeuser${random.nextInt(1000)}@fakeemail.com',
    'hireable': random.nextBool(),
    'bio': 'This is a fake bio',
    'twitter_username': 'fakeuser${random.nextInt(1000)}',
    'public_repos': random.nextInt(100),
    'public_gists': random.nextInt(100),
    'followers': random.nextInt(1000),
    'following': random.nextInt(1000),
    'created_at': createdAt.toIso8601String(),
    'updated_at': updatedAt.toIso8601String(),
  };
}

Future<void> saveUserInfo() async {
  await saveJson('user.json', _clientIdUserInfoMap);
  await saveJson('access_token.json', _accessTokenClientIdMap);
}

Future<void> loadUserInfo() async {
  final accessTokenUserInfoMap = await loadJson('user.json');
  if (accessTokenUserInfoMap != null && accessTokenUserInfoMap is JsonMap) {
    accessTokenUserInfoMap.forEach((k, v) => _clientIdUserInfoMap[k] = v);
  }
  final accessTokenClientIdMap = await loadJson('access_token.json');
  if (accessTokenClientIdMap != null && accessTokenClientIdMap is JsonMap) {
    accessTokenClientIdMap.forEach((k, v) => _accessTokenClientIdMap[k] = v);
  }
}

Future<void> accessTokenCheckAuth(
  String? token,
  Context context,
  Next next,
) async {
  if (!_accessTokenClientIdMap.containsKey(token)) return;
  context.auth = true;
  await next();
}
